import argparse
import heapq
import numpy as np
import pandas as pd
import re
import math

device_cpu_freq_max = {
    'bbk': (1844 + 2189 + 2400) * 1000,
    'pi': (1600 + 2150 + 2500) * 1000,
    'aln': (1530 + 2150 + 2620) * 1000,
    'mrt': (1306 + 2050 + 2285) * 1000,
    'cls': (1600 + 2150 + 2500) * 1000
}

class MetricParser:
    def __init__(self, device_type, input_source):
        self.device_type = device_type.lower()
        self.input_source = input_source
        self.fps_title = 'fps'
        self.fps_jitters_title = 'fpsJitters'
        self.cpu_usage_title_hm = 'TotalcpuUsage'
        self.cpu_usage_title_android = 'cpuLoad'
        self.cpu1_freq_title = 'cpu1ClusterFre'
        self.cpu2_freq_title = 'cpu2ClusterFre'
        if self.device_type == 'bbk':
            # bbk只有8个核，0~3小核 4~6中核 7大核
            self.cpu3_freq_title = 'cpu7Frequency'
        else:
            self.cpu3_freq_title = 'cpu3ClusterFre'

    def parse(self):
        if self.device_type not in device_cpu_freq_max:
            print('Device type {} not supported.'.format(self.device_type))
            return
        for input_path in self.input_source:
            self.parse_one(input_path)

    def parse_one(self, input_path):
        print(f"input path: {input_path}")
        df = pd.read_csv(input_path)
        variance_population = self.calc_fps_population(df)
        one_percent_low_frame = self.calc_fps_low_frame(df)
        cpu_usage = self.calc_cpu_usage(df)
        print('')

        return variance_population, one_percent_low_frame, cpu_usage

    def calc_fps_population(self, df):
        headers = df.columns.tolist()
        if self.fps_title not in headers:
            print(f"Info: '{self.fps_title}' column not found")
            return
        fps_data = df[self.fps_title].tolist()
        print(f"total fps data count: {len(fps_data)}")
        if len(fps_data) == 0:
            return
        # 计算总体方差
        variance_population = np.var(fps_data)
        print(f"帧率方差: {variance_population}")

        # 计算样本方差
        variance_sample = np.var(fps_data, ddof=1)
        print(f"样本方差: {variance_sample}")
        return variance_population

    def calc_fps_low_frame(self, df):
        headers = df.columns.tolist()
        if self.fps_jitters_title not in headers:
            print(f"Info: '{self.fps_jitters_title}' column not found")
            return
        raw_data = df[self.fps_jitters_title].tolist()
        all_fps_data = []
        for data in raw_data:
            if not isinstance(data, str) and math.isnan(data):
                continue
            parts = re.split('[,;]+', data)
            result = [int(x) for x in parts if x]
            all_fps_data.extend(result)

        low_count = round(len(all_fps_data) / 100)
        if low_count < 1:
            low_count = 1
        low_data = heapq.nlargest(low_count, all_fps_data)
        avg = np.average(low_data)
        print(f"1%low帧: {1000 / (avg / 1e6)}")
        return 1000 / (avg / 1e6)

    def calc_cpu_usage(self, df):
        headers = df.columns.tolist()
        if self.cpu_usage_title_hm not in headers and self.cpu_usage_title_android not in headers:
            print(f"Info: '{self.cpu_usage_title_hm}' and '{self.cpu_usage_title_android}' column not found")
            return
        if self.cpu1_freq_title not in headers or self.cpu2_freq_title not in headers or self.cpu3_freq_title not in headers:
            print(f"Info: cpu_freq column not found")
            return
        if self.cpu_usage_title_hm in headers:
            cpu_usage_data = df[self.cpu_usage_title_hm].tolist()
            print(f"CPU usage data title: {self.cpu_usage_title_hm}")
        else:
            cpu_usage_data = df[self.cpu_usage_title_android].tolist()
            print(f"CPU usage data title: {self.cpu_usage_title_android}")

        cpu1_freq = df[self.cpu1_freq_title].tolist()
        cpu2_freq = df[self.cpu2_freq_title].tolist()
        cpu3_freq = df[self.cpu3_freq_title].tolist()
        total_cpu_freq = []
        for i in range(len(cpu1_freq)):
            total_cpu_freq.append(cpu1_freq[i] + cpu2_freq[i] + cpu3_freq[i])
        cpu_usage = []
        for i in range(len(cpu_usage_data)):
            cpu_usage.append(cpu_usage_data[i] * (total_cpu_freq[i] / device_cpu_freq_max[self.device_type]))
        avg = np.average(cpu_usage)
        print(f"cpu usage: {avg}")
        return avg


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('-i', '--input_source',
                        action='append',
                        type=str,
                        help="""input index file""")
    parser.add_argument('-t', '--device_type',
                        action='store',
                        type=str,
                        help="""device type""")
    args = parser.parse_args()
    if not args.input_source:
        print("invalid parameter input_source")
        return
    parser = MetricParser(args.device_type, args.input_source)
    parser.parse()

if __name__ == '__main__':
    main()